home *** CD-ROM | disk | FTP | other *** search
- /*
- * Name: sprite.cpp
- *
- * Author: Chris Bentley 12/3/97, ATI Research Inc. Marlborough, MA
- *
- * Description: This is a simple demo showing the following:
- *
- * 1) using RAVE texture mapped triangles as sprites
- * 2) using RAVE bitmaps as sprites
- * 3) using alpha masking to create transparent sprites
- * 4) using vertex alpha to blend or fade sprites
- * 5) shifting and rotate 2D sprites
- * 6) using texture lighting from vertex colors to tint sprites
- *
- * Note: One restriction is that textures in RAVE must
- * be power-of-two on each side (not necessarily square).
- * Non power-of-two bitmaps can be used by padding out
- * to the next power-of-two and adjusting the u, v texture
- * coordinates appropriately. RAVE 'bitmaps' on the other
- * hand can be any dimensions you want, but you can't rotate
- * and scale them (that's what textures are for :-).
- *
- * I have run this on the Apple software RAVE renderer, and
- * on the ATI RageII and Rage Pro cards. The 'scale' and 'pad'
- * hacks were put in to keep the sprites from running off the edge
- * of the window - with the RAVE software driver this causes very
- * nasty crashes. The ATI hardware does the window clipping for you,
- * so these workarounds are disabled when running on it. This code
- * uses standard RAVE, so it _should_ run on other people's RAVE
- * hardware. Please feel free to use this code in any way you want.
- *
- * Here is some timing info for this code, running on a PowerPC 9600,
- * 64MB RAM, 225 Mhz, 6409x480x16:
- *
- * On Apple RAVE software - 32 fps
- * On ATI RageII hardware - 55 fps
- * On ATI Rage Pro hardware - 165 fps
- *
- * For more info on the RAVE API check out:
- *
- * gemma.apple.com/dev/games/
- *
- * For more info on the latest ATI RAVE hardware and drivers
- * check out:
- *
- * www.atitech.ca
- *
- * or send email to:
- *
- * devrel@atitech.ca (and tell them Chris Bentley sent you :-)
- *
- */
- /****************************************************************/
- /* headers */
- /****************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <Timer.h>
- #include "RAVE.h"
-
- /****************************************************************/
- /* defines */
- /****************************************************************/
- #define LEFT 20
- #define TOP 40
- #define WIDTH 600
- #define HEIGHT 400
-
- #define BRICK_RES_ID 128
- #define SUN_RES_ID 129
-
- #define MBAR_RES_ID 128
-
- #define APPLE_MENU_ID 128
- #define FILE_MENU_ID 129
- #define ENGINE_MENU_ID 130
-
- #define QUIT_ITEM 1
-
- #define MAX_ENGINE 5
-
- /*
- * macro to load fields of TQAVGouraud
- */
- #define SG( v, _x, _y, _z, _invW, _a, _r, _g, _b ) \
- { \
- (v).x = (_x); \
- (v).y = (_y); \
- (v).z = (_z); \
- (v).invW = (_invW); \
- (v).a = (_a); \
- (v).r = (_r); \
- (v).g = (_g); \
- (v).b = (_b); \
- }
-
- /*
- * macro to load fields of TQAVTexture
- */
- #define ST( _v,_x,_y,_z,_invW,_a,_r,_g,_b,_uOverW,_vOverW,_kd_r,_kd_g,_kd_b,_ks_r,_ks_g,_ks_b ) \
- { \
- (_v).x = (_x); \
- (_v).y = (_y); \
- (_v).z = (_z); \
- (_v).invW = (_invW); \
- (_v).a = (_a); \
- (_v).r = (_r); \
- (_v).g = (_g); \
- (_v).b = (_b); \
- (_v).uOverW = (_uOverW); \
- (_v).vOverW = (_vOverW); \
- (_v).kd_r = (_kd_r); \
- (_v).kd_g = (_kd_g); \
- (_v).kd_b = (_kd_b); \
- (_v).ks_r = (_ks_r); \
- (_v).ks_g = (_ks_g); \
- (_v).ks_b = (_ks_b); \
- }
-
- /*
- * macros to update positions of sprites
- */
- #define Translate( _x, _y, _xinc, _yinc, _image ) \
- { \
- if( _x >= WIDTH-pad ) _xinc = -1; \
- if( _x < pad ) _xinc = 1; \
- if( _y >= HEIGHT-pad ) _yinc = -1; \
- if( _y < pad ) _yinc = 1; \
- \
- _x += _xinc; \
- _y += _yinc; \
- \
- V[0].x = _x; \
- V[0].y = _y - _image.height * scale; \
- V[1].x = _x; \
- V[1].y = _y; \
- V[2].x = _x + _image.width * scale; \
- V[2].y = _y; \
- V[3].x = _x + _image.width * scale; \
- V[3].y = _y - _image.height * scale; \
- }
-
- #define Rotate( _x, _y, _angle, _image) \
- { \
- _angle = (_angle == 360) ? 0 : _angle + 5; \
- \
- xoff = _image.width * scale * Cos[_angle]; \
- yoff = _image.height * scale * Sin[_angle]; \
- \
- V[0].x = _x - yoff; \
- V[0].y = _y - xoff; \
- V[1].x = _x; \
- V[1].y = _y; \
- V[2].x = _x + xoff; \
- V[2].y = _y - yoff; \
- V[3].x = V[2].x - yoff; \
- V[3].y = V[2].y - xoff; \
- }
-
- /*
- * utility macros
- */
- #define USHRT_MAX 65535U
- #define ONE_SECOND 1000000
- #define MILLIONTHS 0.000001F
- #define MAX( a, b ) ( ((a) > (b)) ? (a) : (b) )
- #define DEG2RAD( a ) ( (double)((a) * 0.0174532925199432) )
- #define RAD2DEG( a ) ( (double)((a) * 57.295779513082320) )
- #define rand() ((32767+Random()) * 1.0/65536.0)
-
- /****************************************************************/
- /* typedefs */
- /****************************************************************/
- typedef unsigned char UINT8;
- typedef unsigned short UINT16;
- typedef long INT32;
- typedef unsigned long UINT32;
-
- /****************************************************************/
- /* prototypes */
- /****************************************************************/
- /*
- * initialization functions
- */
- void InitTables( void );
- void InitMac( void );
- int InitWindow( void );
- int InitRAVE( void );
- TQAEngine *FindEngine( TQADevice *device );
- GDHandle FindWindowDevice( WindowPtr pWin );
- void FindWindowContentRect( WindowPtr pWin, Rect *r );
- int SetupRAVE( void );
- int SetupRAVETex( void );
- void MenuBarInit( void );
-
- /*
- * Event handling functions
- */
- void EventLoop( void );
- void HandleMouseDown( EventRecord *pevent );
- void HandleMenuChoice( INT32 i32menuChoice );
- void HandleAppleChoice( UINT32 u32TheItem );
- void HandleFileChoice( UINT32 u32TheItem );
- void HandleEngineChoice( UINT32 u32TheItem );
-
- /*
- * utility functions
- */
- void redraw( void );
- void Cleanup( void );
- void DisplayString( int x, int y, char *str );
- UINT32 MicrosecondCount( void );
- int LoadImageFromResource( short resID, UINT8 depth, UINT8 alpha,
- TQAImage *map, TQAImagePixelType *pixelType );
-
- /****************************************************************/
- /* global variables */
- /****************************************************************/
- /*
- * RAVE variables
- */
- GDHandle gGDevice;
- TQADevice gDevice;
- TQAEngine *gEngine;
- TQADrawContext *gDrawContext;
- TQATexture *gpTex;
- TQABitmap *gpBit;
- TQAVTexture V[4];
- TQAVGouraud VG;
- TQAImage gImageTex;
- TQAImage gImageBit;
- TQAImagePixelType pixelType;
- unsigned long gflags = kQAContext_DoubleBuffer | kQAContext_NoZBuffer;
- TQARect gRect = { LEFT, LEFT+WIDTH, TOP, TOP+HEIGHT };
- TQAEngine *EngineList[MAX_ENGINE] = { NULL, NULL, NULL, NULL, NULL };
- char EngineNames[MAX_ENGINE][100];
- unsigned long gEngineID = 0;
-
- /*
- * window variables
- */
- MenuHandle gAppleMenu;
- MenuHandle gFileMenu;
- MenuHandle gEngineMenu;
- Boolean gbDone = false;
- Boolean gbTexAlpha = true;
- Boolean gbATIcard = false;
- int gNumEngines = 0;
- WindowPtr winPtr = NULL;
- Rect winRect = { TOP, LEFT, TOP+HEIGHT, LEFT+WIDTH };
- RGBColor BLACK = { 0, 0, 0 };
- GWorldPtr newGW;
-
- /*
- * sprite + misc variables
- */
- int x1 = 140, y1 = 150;
- int x2 = 230, y2 = 270;
- int x3 = 240, y3 = 175;
- int x4 = 190, y4 = 300;
- int xinc1 = 1, yinc1 = 1;
- int xinc2 = -1, yinc2 = -1;
- int xinc3 = -1, yinc3 = 1;
- int xinc4 = 1, yinc4 = -1;
- UINT32 start, end;
- float seconds;
- UINT32 count = 0;
- float sum = 0.0;
- char str[100];
- int angle = 0;
- float xoff, yoff;
- double Cos[361], Sin[361];
- float pad = 0;
- float scale = 1;
-
- /****************************************************************/
- /* code */
- /****************************************************************/
- /*
- * Function: main()
- *
- */
- void main( void )
- {
- /*
- * initialize sin, cos tables
- */
- InitTables();
-
- /*
- * initialize Toolbox + window
- */
- InitMac();
-
- if( !InitWindow() || !SetupRAVE() )
- {
- Cleanup();
- return;
- }
-
- redraw();
-
- EventLoop();
-
- /*
- * end
- */
- Cleanup();
- }
-
- /*
- * Function: InitTables()
- *
- */
- void InitTables( void )
- {
- for( int angle = 0; angle <= 360; angle++ )
- {
- Cos[angle] = cos( DEG2RAD(angle) );
- Sin[angle] = sin( DEG2RAD(angle) );
- }
- }
-
- /*
- * Function: InitMac()
- *
- */
- void InitMac( void )
- {
- OSErr error;
- SysEnvRec theWorld;
-
- /*
- * Test the computer to be sure we can do color.
- * If not we would crash, which would be bad.
- * If we can’t run, just beep and exit.
- */
- error = SysEnvirons( 1, &theWorld );
- if( theWorld.hasColorQD == false )
- ExitToShell();
-
- /*
- * Initialize all the needed managers.
- */
- InitGraf( &qd.thePort );
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( NULL );
- InitCursor();
-
- GetDateTime((unsigned long*) &qd.randSeed);
-
- MenuBarInit();
- }
-
- /*
- * Function: InitWindow()
- *
- */
- int InitWindow( void )
- {
- if( (winPtr = NewCWindow( NULL, &winRect, "\pRAVE Sprite Demo", true,
- noGrowDocProc, (WindowPtr)-1, false, 0 )) == NULL )
- {
- printf( "ERROR: opening window\n" );
- return( false );
- }
-
- return( true );
- }
-
- /*
- * Function: InitRAVE()
- *
- */
- int InitRAVE( void )
- {
- Rect r;
-
- if( (gGDevice = FindWindowDevice(winPtr)) == NULL )
- {
- printf( "ERROR: No monitors found\n" );
- return( false );
- }
-
- gDevice.deviceType = kQADeviceGDevice;
- gDevice.device.gDevice = gGDevice;
-
- if( (gEngine = FindEngine( &gDevice )) == NULL )
- {
- printf( "ERROR: No Engine available\n" );
- return( false );
- }
-
- if( QAEngineCheckDevice( gEngine, &gDevice ) )
- {
- printf( "ERROR: EngineCheckDevice failed\n" );
- return( false );
- }
-
- FindWindowContentRect( winPtr, &r );
- OffsetRect( &r, -(**gGDevice).gdRect.left, -(**gGDevice).gdRect.top );
-
- gRect.left = r.left;
- gRect.top = r.top;
- gRect.right = r.right;
- gRect.bottom = r.bottom;
-
- return( true );
- }
-
- void FindWindowContentRect( WindowPtr pWin, Rect *r )
- {
- GrafPtr oldPort;
- Point leftTop;
- Point rightBot;
-
- GetPort( &oldPort );
-
- SetPort( pWin );
- SetPt( &leftTop, pWin->portRect.left, pWin->portRect.top );
- SetPt( &rightBot, pWin->portRect.right, pWin->portRect.bottom );
-
- LocalToGlobal( &leftTop );
- LocalToGlobal( &rightBot );
-
- SetRect( r, leftTop.h, leftTop.v, rightBot.h, rightBot.v );
-
- SetPort( oldPort );
- }
-
- /*
- * Function: FindWindowDevice()
- *
- */
- GDHandle FindWindowDevice( WindowPtr pWin )
- {
- GDHandle hDevice;
- Rect rWin;
- Rect intersect;
-
- if( pWin == NULL )
- return( NULL );
-
- rWin = ((*(((WindowPeek)pWin)->strucRgn))->rgnBBox);
-
- for( hDevice = GetDeviceList();
- hDevice;
- hDevice = GetNextDevice(hDevice) )
- {
- /*
- * test for active monitors that entirely contain rect
- */
- if( TestDeviceAttribute(hDevice, screenDevice) &&
- TestDeviceAttribute(hDevice, screenActive) &&
- SectRect(&rWin, &((*hDevice)->gdRect), &intersect) &&
- EqualRect(&rWin, &intersect) )
- {
- return( hDevice );
- }
- }
-
- return( NULL );
- }
-
- TQAEngine *FindEngine( TQADevice *device )
- {
- TQAEngine *tmpEngine;
- UINT32 vendorID;
- char Response[200];
- int i, len;
- int saveEngineID;
- Str255 menuStr;
- MenuHandle menuHndl = gEngineMenu;
-
- saveEngineID = gEngineID;
- gEngineID = 0;
-
- for( i = 0; i < gNumEngines; i++ )
- {
- CheckItem( gEngineMenu, i+1, false );
- DisableItem( gEngineMenu, i+1 );
- }
-
- /*
- * list all RAVE engines
- */
- for( tmpEngine = QADeviceGetFirstEngine(device);
- tmpEngine;
- tmpEngine = QADeviceGetNextEngine(device, tmpEngine) )
- {
- QAEngineGestalt( tmpEngine, kQAGestalt_ASCIIName, Response );
-
- /*
- * see if engine is already in list
- */
- for( i = 0; i < gNumEngines; i++ )
- {
- if( strcmp(Response, EngineNames[i]) == 0 )
- {
- EngineList[i] = tmpEngine;
- EnableItem( gEngineMenu, i+1 );
-
- if( i == saveEngineID )
- gEngineID = i;
- break;
- }
- }
-
- /*
- * if engine is not already in list add it
- */
- if( i == gNumEngines )
- {
- EngineList[gNumEngines] = tmpEngine;
- strcpy( EngineNames[gNumEngines], Response );
-
- menuStr[0] = strlen( Response );
- strcpy( (char *)(menuStr+1), Response );
-
- AppendMenu( gEngineMenu, menuStr );
-
- if( ++gNumEngines == MAX_ENGINE )
- break;
- }
- }
-
- if( gEngineID >= gNumEngines )
- gEngineID = 0;
-
- CheckItem( gEngineMenu, gEngineID+1, true );
-
- QAEngineGestalt( EngineList[gEngineID], kQAGestalt_VendorID, &vendorID );
- gbATIcard = (vendorID == 1);
-
- return( EngineList[gEngineID] );
- }
-
- int SetupRAVE( void )
- {
- if( !InitRAVE() )
- return( false );
-
- /*
- * create a draw context + set background color for clearing
- */
- if( QADrawContextNew(&gDevice,&gRect,0,gEngine,gflags,&gDrawContext) != kQANoErr )
- {
- printf( "ERROR: Context create failed\n" );
- Cleanup();
- return( false );
- }
-
- QASetFloat( gDrawContext, kQATag_ColorBG_a, 1.0 );
- QASetFloat( gDrawContext, kQATag_ColorBG_r, 1.0 );
- QASetFloat( gDrawContext, kQATag_ColorBG_g, 0.0 );
- QASetFloat( gDrawContext, kQATag_ColorBG_b, 0.0 );
-
- /*
- * load image for texture
- */
- if( !LoadImageFromResource(SUN_RES_ID, 16, true, &gImageTex, &pixelType) )
- {
- printf( "ERROR: loading bitmap resource failed\n" );
- Cleanup();
- return( false );
- }
-
- /*
- * register texture with RAVE
- */
- QATextureNew( gEngine, kQATexture_None, pixelType, &gImageTex, &gpTex );
-
- if( gpTex == NULL )
- {
- printf( "ERROR: RAVE bitmap registration failed\n" );
- Cleanup();
- return( false );
- }
-
- QATextureDetach( gEngine, gpTex );
- DisposeGWorld( newGW );
-
- /*
- * load image
- */
- if( !LoadImageFromResource(BRICK_RES_ID, 16, false, &gImageBit, &pixelType) )
- {
- printf( "ERROR: loading bitmap resource failed\n" );
- Cleanup();
- return( false );
- }
-
- /*
- * register bitmap with RAVE
- */
- QABitmapNew( gEngine, kQABitmap_None, pixelType, &gImageBit, &gpBit );
-
- if( gpBit == NULL )
- {
- printf( "ERROR: RAVE bitmap registration failed\n" );
- Cleanup();
- return( false );
- }
-
- QABitmapDetach( gEngine, gpBit );
- DisposeGWorld( newGW );
-
- /*
- * initialize Gouraud vertex for anchoring top left corner of bitmap sprite
- */
- // x y z 1/W a r g b
- SG( VG, 0, 0, 1, 1, 1, 1, 1, 1 );
-
- /*
- * initialize corners of 2 triangles to form rectangle for texture sprite
- * in the render loop we will only be updating the x, y coords,
- * and on the third sprite we will set the vertex alpha to 0.1,
- * to make the entire sprite blend with the background, then reset
- * the vertex alpha to 1
- *
- * 0-----3
- * |\ |
- * | \ |
- * | \ |
- * | \ |
- * | \|
- * 1-----2
- *
- */
- // x y z 1/W a r g b u/W v/W dr dg db sr sg sb
- ST( V[0], 0, 0, 1, 1, 1, 1, 1, 1, 0.0, 1.0, 0, 1, 0, 0, 0, 0.5 );
- ST( V[1], 0, 0, 1, 1, 1, 1, 1, 1, 0.0, 0.0, 0, 1, 0, 0, 0, 0.5 );
- ST( V[2], 0, 0, 1, 1, 1, 1, 1, 1, 1.0, 0.0, 0, 1, 0, 0, 0, 0.5 );
- ST( V[3], 0, 0, 1, 1, 1, 1, 1, 1, 1.0, 1.0, 0, 1, 0, 0, 0, 0.5 );
-
- return( true );
- }
-
- void MenuBarInit( void )
- {
- Handle mBarHndl;
-
- mBarHndl = GetNewMBar( MBAR_RES_ID );
- SetMenuBar( mBarHndl );
-
- gAppleMenu = GetMenu( APPLE_MENU_ID );
- gFileMenu = GetMenu( FILE_MENU_ID );
- gEngineMenu = GetMenu( ENGINE_MENU_ID );
-
- AppendResMenu( gAppleMenu, 'DRVR' );
-
- DrawMenuBar();
- }
-
- void EventLoop( void )
- {
- EventRecord event;
-
- while( !gbDone )
- {
- WaitNextEvent( everyEvent, &event, 60L, NULL );
-
- switch( event.what )
- {
- case mouseDown: HandleMouseDown( &event ); break;
- case updateEvt: break;
- case nullEvent: break;
- default: break;
- }
- }
- }
-
- void HandleMouseDown( EventRecord *pevent )
- {
- WindowPtr pWin;
-
- switch( FindWindow( pevent->where, &pWin ) )
- {
- case inMenuBar: HandleMenuChoice( MenuSelect( pevent->where ) ); break;
- case inSysWindow: SystemClick( pevent, pWin ); redraw(); break;
- case inGoAway: gbDone = (TrackGoAway(pWin, pevent->where) == true); break;
- case inContent: redraw(); break;
- case inDrag: DragWindow( pWin, pevent->where, &qd.screenBits.bounds );
- Cleanup();
-
- if( !SetupRAVE() )
- Cleanup();
-
- redraw();
- break;
- default: break;
- }
- }
-
- void HandleMenuChoice( INT32 i32menuChoice )
- {
- if( i32menuChoice == 0 )
- return;
-
- switch( HiWord( i32menuChoice ) )
- {
- case APPLE_MENU_ID: HandleAppleChoice( LoWord(i32menuChoice) ); break;
- case FILE_MENU_ID: HandleFileChoice( LoWord(i32menuChoice) ); break;
- case ENGINE_MENU_ID: HandleEngineChoice( LoWord(i32menuChoice) ); break;
- default: break;
- }
-
- HiliteMenu( 0 );
- }
-
- void HandleAppleChoice( UINT32 u32TheItem )
- {
- Str255 strAccName;
-
- switch( u32TheItem )
- {
- default: GetMenuItemText( gAppleMenu, u32TheItem, strAccName );
- OpenDeskAcc( strAccName );
- break;
- }
- }
-
- void HandleFileChoice( UINT32 u32TheItem )
- {
- switch( u32TheItem )
- {
- case QUIT_ITEM: gbDone = true; break;
- default: break;
- }
- }
-
- void HandleEngineChoice( UINT32 u32TheItem )
- {
- UINT32 vendorID;
-
- for( int i = 1; i <= gNumEngines; i++ )
- CheckItem( gEngineMenu, i, false );
-
- gEngineID = u32TheItem-1;
- gEngine = EngineList[gEngineID];
-
- QAEngineGestalt( gEngine, kQAGestalt_VendorID, &vendorID );
- gbATIcard = ( vendorID == 1 );
-
- if( QAEngineCheckDevice( gEngine, &gDevice ) )
- printf( "ERROR: EngineCheckDevice failed\n" );
-
- CheckItem( gEngineMenu, u32TheItem, true );
-
- Cleanup();
-
- if( !SetupRAVE() )
- Cleanup();
-
- redraw();
- }
-
- /*
- * Function: Cleanup()
- *
- */
- void Cleanup( void )
- {
- if( gpTex )
- {
- QATextureDelete( gEngine, gpTex );
- gpTex = NULL;
- }
-
- if( gpBit )
- {
- QABitmapDelete( gEngine, gpBit );
- gpBit = NULL;
- }
-
- if( gDrawContext )
- {
- QADrawContextDelete( gDrawContext );
- gDrawContext = NULL;
- }
- }
-
- void redraw( void )
- {
- if( gbATIcard )
- {
- scale = 1.0;
- pad = 0.0;
- }
- else
- {
- scale = 0.5;
- pad = 175;
-
- }
-
- count = 0;
- sum = 0.0;
-
- while( !Button() )
- {
- start = MicrosecondCount();
-
- /*
- * render loop
- */
- QARenderStart( gDrawContext, NULL, NULL);
-
- /*
- * set current texture
- */
- QASetPtr( gDrawContext, kQATag_Texture, gpTex );
-
- /*
- * shift first texture 'sprite' + set texture lighting to highlight
- */
- Translate( x1, y1, xinc1, yinc1, gImageTex );
- QASetInt( gDrawContext, kQATag_TextureOp, kQATextureOp_Highlight );
- QADrawTriTexture( gDrawContext, &V[0], &V[1], &V[2], kQATriFlags_None );
- QADrawTriTexture( gDrawContext, &V[0], &V[2], &V[3], kQATriFlags_None );
-
- /*
- * shift and rotate second texture 'sprite' + set texture lighting to modulate
- */
- Translate( x2, y2, xinc2, yinc2, gImageTex );
- Rotate( x2, y2, angle, gImageTex );
- QASetInt( gDrawContext, kQATag_TextureOp, kQATextureOp_Modulate );
- QADrawTriTexture( gDrawContext, &V[0], &V[1], &V[2], kQATriFlags_None );
- QADrawTriTexture( gDrawContext, &V[0], &V[2], &V[3], kQATriFlags_None );
-
- /*
- * shift third texture 'sprite' with vertex transparency + turn off texture lighting
- */
- Translate( x3, y3, xinc3, yinc3, gImageTex );
- V[0].a = V[1].a = V[2].a = V[3].a = 0.1;
- QASetInt( gDrawContext, kQATag_TextureOp, kQATextureOp_None );
- QADrawTriTexture( gDrawContext, &V[0], &V[1], &V[2], kQATriFlags_None );
- QADrawTriTexture( gDrawContext, &V[0], &V[2], &V[3], kQATriFlags_None );
- V[0].a = V[1].a = V[2].a = V[3].a = 1.0;
-
- /*
- * shift bitmap 'sprite'
- */
- Translate( x4, y4, xinc4, yinc4, gImageBit );
- VG.x = x4; VG.y = y4;
- QADrawBitmap( gDrawContext, &VG, gpBit );
-
- QARenderEnd( gDrawContext, NULL );
-
- /*
- * display frame rate
- */
- end = MicrosecondCount();
- seconds = (float)(MAX((end-start),1))*MILLIONTHS;
- sum += seconds;
- sprintf( str, "fps = %5.2f, avg = %5.2f", 1.0/seconds, ++count/sum );
- DisplayString( 2, 10, str );
- }
- }
-
- /*
- * Function: DisplayString()
- *
- */
- void DisplayString( int x, int y, char *str )
- {
- char buf[256];
-
- if( !winPtr )
- return;
-
- SetPort( winPtr );
- RGBForeColor( &BLACK );
- MoveTo( x, y );
-
- strcpy( buf+1, str );
- buf[0] = strlen( buf+1 );
- DrawString( (const unsigned char *)buf );
- }
-
- /*
- * Function: MicrosecondCount()
- *
- */
- UINT32 MicrosecondCount( void )
- {
- UnsignedWide currentCount;
-
- Microseconds(¤tCount);
-
- return( currentCount.lo );
- }
-
- /*
- * Function: LoadImageFromResource()
- *
- */
- int LoadImageFromResource( short resID, UINT8 depth, UINT8 alpha,
- TQAImage *map, TQAImagePixelType *pixelType )
- {
- PicHandle hPict;
- Rect pictRect;
- GDHandle saveGD;
- GWorldPtr saveGW;
- PixMapHandle pixHndl;
- PixMapPtr pixPtr;
-
- /*
- * determine target pixel type
- */
- switch( depth )
- {
- case 8: *pixelType = kQAPixel_CL8; break;
- case 16: *pixelType = (alpha) ? kQAPixel_ARGB16 : kQAPixel_RGB16; break;
- case 32: *pixelType = (alpha) ? kQAPixel_ARGB32 : kQAPixel_RGB32; break;
- default: return( false );
- }
-
- /*
- * load PICT resource and get bounding rect
- */
- if( (hPict = GetPicture( resID )) == NULL )
- return( false );
-
- pictRect = (**hPict).picFrame;
-
- /*
- * setup GWorld to draw pict into
- */
- GetGWorld( &saveGW, &saveGD );
-
- if( NewGWorld(&newGW, depth, &pictRect, NULL, NULL, NULL) != noErr )
- {
- ReleaseResource( (Handle)hPict );
- return( false );
- }
-
- LockPixels( newGW->portPixMap );
- SetGWorld( newGW, NULL );
-
- DrawPicture(hPict, &pictRect );
-
- /*
- * setup TQAImage struct with GWorld pixmap data
- */
- pixHndl = GetGWorldPixMap( newGW );
- pixPtr = *pixHndl;
- map->width = pictRect.right - pictRect.left;
- map->height = pictRect.bottom - pictRect.top;
- map->rowBytes = (UINT32)(pixPtr->rowBytes & 0x7fff);
- map->pixmap = GetPixBaseAddr( pixHndl );
-
- /*
- * Hack to demo sprite with alpha transparency -
- * detect white pixels (in 'Sun' PICT from Scrapbook)
- * and set their alpha bit to 0 for transparency
- */
- if( alpha )
- {
- UINT8 *u8ptr = (UINT8 *)map->pixmap;
- UINT16 *u16ptr;
-
- for( int y = 0; y < map->height; y++ )
- {
- u16ptr = (UINT16 *)u8ptr;
-
- for( int x = 0; x < map->width; x++ )
- {
- if( (u16ptr[x] & 0x7FFF) == 0x7FFF )
- u16ptr[x] &= 0x8000;
- else
- u16ptr[x] |= 0x8000;
- }
-
- u8ptr += map->rowBytes;
- }
- }
-
- /*
- * free PICT resource, delete temp GWorld,
- * and restore old GWorld
- */
- ReleaseResource( (Handle)hPict );
- SetGWorld( saveGW, saveGD );
-
- return( true );
- }
-
-